/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tuananh.radnom.model.iputils;

/**
 *
 * @author vlad
 * Contain tools for manipulate IP addresses, netmasks etc
 */
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetTools {

    // Cut long values (usually after function NOT)
    static final long BITS32 = 0xFFFFFFFFL;

    // Convert IP address (string) to number
    public static long AddressToNum(String ip_Address) throws UnknownHostException {
        InetAddress Address = InetAddress.getByName(ip_Address);
        long ip_value = (long) Address.hashCode() & BITS32;
        return ip_value;
    }

    // Convert IP address (number) to string
    public static String NumToAddress(long ip_Address) throws UnknownHostException {
        byte[] ip = new byte[4];
        long workAddress = (long) ip_Address & BITS32;
        int mask = 0x000000FF;
        ip[0] = (byte) ((workAddress >> 24) & mask);
        ip[1] = (byte) ((workAddress >> 16) & mask);
        ip[2] = (byte) ((workAddress >> 8) & mask);
        ip[3] = (byte) (workAddress & mask);

        InetAddress Address = InetAddress.getByAddress(ip);
        String host_IP = Address.getHostAddress();
        return host_IP;
    }

    // Convert mask(number) in CIDR format
    public static String convertMask(long mask) {
        String maskStr = "";
        // Try to optimize
        if (mask == 0xFFFFFF00L) {
            maskStr = "24";
        }
        if (mask == 0xFFFF0000L) {
            maskStr = "16";
        }
        if (mask == 0xFF000000L) {
            maskStr = "8";
        } else {
            // Don't hit a target? Check all range
            long varMask = 0x00L;
            for (int i = 0; i < 31; i++) {
                varMask = (long) 1 << (31 - i);
                if ((mask & varMask) == 0) {
                    maskStr = Integer.toString(i);
                    break;
                }
            }
        }
        return maskStr;
    }


    // Convert mask(CIDR and full form) to number
    public static long convertMask(String Mask) throws UnknownHostException {

        long maskValue = 0L;

        if (Mask.length() > 3) {
            // If Mask in full format use AddressToNum
            maskValue = AddressToNum(Mask);
        } else {
            // Else (CIDR format) we need calculate bits
            int bitsMask = Integer.decode(Mask);
            for (int i = 0; i < bitsMask; i++) {
                //System.out.println("Mask = " + Long.toHexString(maskValue));
                maskValue |= (long) 1 << (31 - i);
            }
        }
        return maskValue;
    }

    // Convert BYTE to HEX String
    public static String byteToHex(byte b) {
        String hexDig = Integer.toHexString(b);
        while (hexDig.length() < 2) {
            hexDig = "0" + hexDig;
        }
        hexDig = hexDig.substring(hexDig.length() - 2);
        return hexDig.toUpperCase();
    }

    // Convert MAC address to String form (HEX)
    public static String MACtoString(byte[] macAddress) {
        String res = "";
        int number = 0;
        for (byte b : macAddress) {
            if (!res.isEmpty()) {
                res += "-";
            }
            res = res + byteToHex(b);
            if (++number>5) break;
        }
        return res;
    }

    static public String getNetworkClass(long networkAddress) {
        /* Description networks
         *
         * 192.168.0.0/16 => Private Internet,http://www.ietf.org/rfc/rfc1918.txt
         * 172.16.0.0/12  => Private Internet,http://www.ietf.org/rfc/rfc1918.txt
         * 10.0.0.0/8     => Private Internet,http://www.ietf.org/rfc/rfc1918.txt
         * 169.254.0.0/16 => APIPA,http://www.ietf.org/rfc/rfc3330.txt
         * 127.0.0.0/8    => Loopback,http://www.ietf.org/rfc/rfc1700.txt
         * 224.0.0.0/4"    => Multicast,http://www.ietf.org/rfc/rfc3171.txt
         */
        long workAddress = (long) networkAddress & BITS32;

        String baseClass = "";
        long classVar = (long) workAddress >> 16;
        //classVar &=
        if ((classVar & 0x8000) == 0) {
            baseClass = "Class A";
            if (classVar == 0x7F00) {
                baseClass += ", Loopback";
            } else if (classVar == 0x0A00) {
                baseClass += ", Private Internet";
            }


        } else if ((classVar & 0xC000) == 0x8000) {
            baseClass = "Class B";
            System.out.println(Long.toHexString(classVar));
            if (classVar == 0xA9FE) { // 169.254.0.0/16
                baseClass += ", APIPA";
            } else if (classVar == 0xAC10) { // 172.16.0.0/12
                baseClass += ", Private Internet";
            }
        } else if ((classVar & 0xE000) == 0xC000) {
            baseClass = "Class C";
            if (classVar == 0xC0A8) { // 192.168.0.0/16
                baseClass += ", private Internet";
            }

        } else if ((classVar & 0xF000) == 0xE000) {
            baseClass = "Class D, multicast";
        } else {
            baseClass = "Class Invalid";
        }


        return baseClass;
    }
}
